package com.mathdroid.crawler.armor;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.mathdroid.crawler.shared.EItemStat;
import com.mathdroid.crawler.shared.ERarity;
import com.mathdroid.crawler.shared.Item;



public class ItemPageParser {
	
	private static final String IMAGE_PATTERN = "tor.zamimg.com/torhead/images/icons/backgrounds/swtor/large/.*\\.jpg";
	
	private static final String DMG_TYPE_PATTERN = "Kinetic|Energy";
	
	//+103 Aim<br />
	private static final String STAT_PATTERN = "\\+\\d+ [\\w\\s]+<br />";
	
	//<br />321.0-597.0 Energy Damage<br />
	private static final String DMG_PATTERN = "<br />\\d+\\.0-\\d+\\.0 \\w+ Damage";
	
	//<title>Battlemaster Combat Medic's Cannon - Items - Star Wars:
	private static final String ITEM_NAME = "<title>[\\S\\s]+? -";
	
	//Power Crystal (56)
	private static final String MODULE_NAME = "Power Crystal \\(\\d+\\)|Support \\(\\d+\\)|Barrel \\(\\d+\\)|Overlay \\(\\d+\\)|Color Cartridge \\(\\d+\\)|Emitter Matrix \\(\\d+\\)|Focus Lense \\(\\d+\\)|Hilt \\(\\d+\\)|Power Cell \\(\\d+\\)|Scope \\(\\d+\\)|Trigger \\(\\d+\\)|Harness \\(\\d+\\)|Circuitry \\(\\d+\\)|Underlay \\(\\d+\\)";
	
	private static final String MODS_ARE_NEXT_PATTERN = "Item Modifications";
	
	//Modulator: Open
	private static final String MODULE_SLOT_PATTERN = "<div>[\\w\\s]+: Open";
	
	//<div class="swtt-name sw-q6">Modified DTB-27 Bolt Pistol</div>
	private static final String QUALITY_PATTERN = "class=\"thtt-name sw-q\\d\">";
	
	//<div class="swtt-usedesc">Use: Increases Shield Rating and Absorb Rating by 235 for 20 seconds.</div>
	private static final String USE_PATTERN = "<div class=\"thtt-usedesc\">Use: [\\S\\s]+?</div>";
	
//	Item Qualities
//	.sw-q0,.sw-q0 a{color:#8f8f8f !important;}
//	.sw-q2,.sw-q2 a{color:#ffffff !important;}
//	.sw-q3,.sw-q3 a{color:#00fa00 !important;}
//	.sw-q4,.sw-q4 a{color:#1d8afa !important;}
//	.sw-q5,.sw-q5 a{color:#a335ee !important;}
//	.sw-q6,.sw-q6 a{color:#ff8000 !important;}
//	.sw-q7,.sw-q7 a{color:#e5cc80 !important;}
//	.sw-q8,.sw-q8 a{color:#e5cc80 !important;}
//	.sw-q9,.sw-q9 a{color:#ffff98 !important;}
//	.sw-q10,.sw-q10 a{color:#71d5ff !important;}
//	.sw-q11,.sw-q11 a{color:#ff4040 !important;}
	private HashMap<String, ERarity> qualityMapping = 
		new HashMap<String, ERarity>();
	
	public Item item = new Item();
	
	private int moduleIteration = 0;
	private boolean titleDone = false;
	private boolean jpgDone = false;
	private boolean dmgTypeDone = false;
	private boolean dmgDone = false;
	private boolean qualityDone = false;
	private boolean totalStatsDone = false;
	private boolean useDone = false;
	
	public ItemPageParser(final String ilvl, EItemSlot slot, String torheadid) {
		this.qualityMapping.put("sw-q0", ERarity.CHEAP);
		this.qualityMapping.put("sw-q5", ERarity.ARTIFACT);
		this.qualityMapping.put("sw-q7", ERarity.LEGACY);
		this.qualityMapping.put("sw-q6", ERarity.LEGENDARY);
		this.qualityMapping.put("sw-q3", ERarity.PREMIUM);
		this.qualityMapping.put("sw-q4", ERarity.PROTOTYPE);
		this.qualityMapping.put("sw-q2", ERarity.STANDARD);
		
		this.item.itemlevel = ilvl;
		this.item.slots.add(slot.toString());
		this.item.torheadid = torheadid;
	}
	
	public void parse(String s) {
		String extracted = null;
		
		// module names and ilvl:
		extracted = this.match(MODULE_NAME, s);
		if (extracted != null) {
			String modName = this.extract("", " \\(\\d+\\)", extracted);
			String modilvl = this.extract("[\\s\\w]+ \\(", "\\)", extracted);
			this.item.moduleNames.add(modName);
			this.item.moduleilvl.add(modilvl);
			this.item.stats.add(new HashMap<String, String>());
			this.moduleIteration++;
		}
		
		// the title:
		if (!this.titleDone) {
			extracted = this.match(ITEM_NAME, s);
			if (extracted != null) {
				extracted = this.extract("<title>", " -", extracted);
				this.item.name = extracted;
				this.titleDone = true;
			}
		}

		
		// the one JPG:
		if (!this.jpgDone) {
			extracted = this.match(IMAGE_PATTERN, s);
			if (extracted != null) {
				extracted = this.extract("tor.zamimg.com/torhead/images/icons/backgrounds/swtor/large/", ".jpg", extracted);
				this.item.image = extracted;
				this.jpgDone = true;
				
				//download the image
				try {
					URL imgurl = new URL("http://tor.zamimg.com/torhead/images/icons/backgrounds/swtor/large/" + this.item.image + ".jpg");
					InputStream in = imgurl.openStream();
					OutputStream out = new BufferedOutputStream(
							new FileOutputStream("item-images/"
									+ this.item.image + ".jpg"));
					for (int b; (b = in.read()) != -1;) {
						out.write(b);
					}
					out.close();
					in.close();

				} catch (MalformedURLException e) {
					e.printStackTrace();
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
		// the quality:
		if (!this.qualityDone) {
			extracted = this.match(QUALITY_PATTERN, s);
			if (extracted != null) {
				extracted = this.extract("class=\"thtt-name ", "\">", extracted);
				
				this.item.rarity = this.qualityMapping.get(extracted).toString();
				this.qualityDone = true;
			}
		}

		
		// the dmg type:
		if (!this.dmgTypeDone) {
			extracted = this.match(DMG_TYPE_PATTERN, s);
			if (extracted != null) {
				this.item.stats.get(0).put(EItemStat.DAMAGE_TYPE.getXMLtag(), extracted);
				this.dmgTypeDone = true;
			}
		}
		
		// check when the total stats part is done and the modules are coming next
		if (!this.totalStatsDone) {
			extracted = this.match(MODS_ARE_NEXT_PATTERN, s);
			if (extracted != null) {
				this.totalStatsDone = true;
			}
		}

		
		// the dmg:
		if (!this.dmgDone) {
			extracted = this.match(DMG_PATTERN, s);
			if (extracted != null) {
				String minDmg = this.extract("<br />", "-\\d+\\.0 [\\S\\s]+", extracted);
				String maxDmg = this.extract("<br />\\d+\\.0-", " [\\S\\s]+", extracted);
				this.item.stats.get(0).put(EItemStat.MIN_DAMAGE.getXMLtag(), minDmg);
				this.item.stats.get(0).put(EItemStat.MAX_DAMAGE.getXMLtag(), maxDmg);
				this.dmgDone = true;
			}
		}

		
		// stats:
		extracted = this.match(STAT_PATTERN, s);
		if (extracted != null) {
			String statValue = this.extract("\\+", " [\\w\\s]+<br />", extracted);
			String statType = this.extract("\\+\\d+ ", "<br />", extracted);
			statType = statType.toLowerCase();
			statType = statType.replaceAll("\\s", "");
			this.item.stats.get(this.moduleIteration).put(statType, statValue);
		}
		
		// open module slots:
		LinkedList<String> openModuleSlots = this.matches(MODULE_SLOT_PATTERN, s);
		for (String openSlot : openModuleSlots) {
			openSlot = this.extract("<div>", ": Open", openSlot);
			if (this.item.openModules.containsKey(openSlot)) {
				int counter = this.item.openModules.get(openSlot);
				counter++;
				this.item.openModules.put(openSlot, counter);
			} else {
				this.item.openModules.put(openSlot, 1);
			}
		}
		
		// use effect:
		if (!this.useDone) {
			extracted = this.match(USE_PATTERN, s);
			if (extracted != null) {
				this.useDone = true;
				this.item.use = this.extract("<div class=\"thtt-usedesc\">", "</div>", extracted);
			}
		}

	}
	
	public static void main(final String[] args) {
		ItemPageParser p = new ItemPageParser("", EItemSlot.CHEST, "");
		p.test();
		
	}
	
	private void test() {
		String extracted = null;
		String s = "<div class=\"swtt-usedesc\">Use: testestest test 123.</div>";
		
		extracted = this.match(USE_PATTERN, s);
		if (extracted != null) {
			this.useDone = true;
			extracted = this.extract("<div class=\"swtt-usedesc\">", "</div>", extracted);
			System.out.println(extracted);
		}
	}

	private String match(final String p, final String text) {
		String result = null;
		
		Pattern pattern = Pattern.compile(p);
		Matcher matcher = pattern.matcher(text);
		
		while (matcher.find()) {
			result = matcher.group();
		}
		
		return result;
	}
	
	private LinkedList<String> matches(String p, String text) {
		LinkedList<String> results = new LinkedList<String>();
		
		Pattern pattern = Pattern.compile(p);
		Matcher matcher = pattern.matcher(text);
		
		while (matcher.find()) {
			results.add(matcher.group());
		}
		
		return results;
	}
	
	private String extract(final String start, final String end, final String text) {
		String result = null;
		
		Pattern startpattern = Pattern.compile(start);
		Pattern endpattern = Pattern.compile(end);
		
		Matcher matcher = startpattern.matcher(text);
		result = matcher.replaceAll("");
		
		matcher = endpattern.matcher(result);
		result = matcher.replaceAll("");
		
		return result;
	}
}
